package net.pws.common.security.spi.resource;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import net.pws.common.util.StringUtils;


public class DefaultCachedResource implements ICachedResource {
    
    private List<IResource> resourceList;
    
    private Map<String, IResource> resourceMap = new HashMap<String, IResource>();
    
    private Map<String, IResource> urlResourceMap = new HashMap<String, IResource>();
    
    public DefaultCachedResource(List<IResource> resources) {
        super();
        this.resourceList = resources;
        hierarchicalToFlat(resources, resourceMap, urlResourceMap);
    }
    
    private void hierarchicalToFlat(List<? extends IResource> resList,
                                    Map<String, IResource> resMap,
                                    Map<String, IResource> urlResMap) {
        for (IResource resource : resList) {
            resMap.put(resource.getId(), resource);
            urlResMap.put(resource.getUrl(), resource);
            hierarchicalToFlat(resource.getChildren(), resMap, urlResMap);
        }
    }
    
//    private void hierarchicalToFlat(IResource[] reses,
//                                    Map<String, IResource> resMap,
//                                    Map<String, IResource> urlResMap) {
//        for (IResource resource : reses) {
//            resMap.put(resource.getId(), resource);
//            urlResMap.put(resource.getUrl(), resource);
//            hierarchicalToFlat(resource.getChildren(), resMap, urlResMap);
//        }
//    }
    
    public boolean allowedResource(String resourceId) {
        IResource resource = resourceMap.get(resourceId);
        if (null == resource) {
            return false;
        }
        return !resource.isForbidden();
    }
    
    public boolean allowedUrl(String url) {
        IResource resource = urlResourceMap.get(url);
        if (null == resource) {
            return false;
        }
        return !resource.isForbidden();
    }
    
    public boolean forbiddenResource(String resourceId) {
        IResource resource = resourceMap.get(resourceId);
        if (null == resource) {
            return false;
        }
        return resource.isForbidden();
    }
    
    public boolean forbiddenUrl(String url) {
        IResource resource = resourceMap.get(url);
        if (null == resource) {
            return false;
        }
        return !resource.isForbidden();
    }
    
    public IResource getResource(String resourceId) {
        return resourceMap.get(resourceId);
    }
    
    public IResource[] getResourceChildren(String resourceId, String type) {
        if (StringUtils.isEmpty(resourceId) || StringUtils.isEmpty(type)) {
            return IResource.EMPTY_RESOURCES;
        }
        
        IResource resource = resourceMap.get(resourceId);
        if (null == resource) {
            return IResource.EMPTY_RESOURCES;
        }
        
        List<IResource> result = new ArrayList<IResource>();
        
        for (Object child : resource.getChildren()) {
            if (type.equals(((IResource) child).getType())) {
                result.add((IResource) child);
            }
        }
        
        return result.toArray(IResource.EMPTY_RESOURCES);
    }
    
    public IResource[] getResourceChildren(String resourceId,
                                           String type,
                                           boolean allowed) {
        if (StringUtils.isEmpty(resourceId) || StringUtils.isEmpty(type)) {
            return IResource.EMPTY_RESOURCES;
        }
        
        IResource resource = resourceMap.get(resourceId);
        if (null == resource) {
            return IResource.EMPTY_RESOURCES;
        }
        
        List<IResource> result = new ArrayList<IResource>();
        
        for (Iterator<? extends IResource> iterator = resource.getChildren().iterator(); iterator.hasNext();) {
            IResource child = iterator.next();
            if (type.equals(child.getType()) && (child.isForbidden() != allowed)) {
                result.add(child);
            }
        }
        
        return result.toArray(IResource.EMPTY_RESOURCES);
    }
    
    public IResource[] getResourceChildren(String resourceId) {
        if (StringUtils.isEmpty(resourceId)) {
            return IResource.EMPTY_RESOURCES;
        }
        IResource resource = resourceMap.get(resourceId);
        if (null == resource) {
            return IResource.EMPTY_RESOURCES;
        }
        return (IResource[]) resource.getChildren()
                                     .toArray(IResource.EMPTY_RESOURCES);
    }
    
    public IResource[] getResourceChildren(String resourceId, boolean allowed) {
        if (StringUtils.isEmpty(resourceId)) {
            return IResource.EMPTY_RESOURCES;
        }
        IResource resource = resourceMap.get(resourceId);
        if (null == resource) {
            return IResource.EMPTY_RESOURCES;
        }
        
        List<IResource> result = new ArrayList<IResource>();
        
        for (Iterator<? extends IResource> iterator = resource.getChildren().iterator(); iterator.hasNext();) {
            IResource child = (IResource) iterator.next();
            if ((child.isForbidden() != allowed)) {
                result.add(child);
            }
        }
        
        return result.toArray(IResource.EMPTY_RESOURCES);
    }
    
    public IResource[] getResources() {
        return (IResource[]) resourceList.toArray(IResource.EMPTY_RESOURCES);
    }
    
    public IResource[] getResources(boolean allowed) {
        List<IResource> result = new ArrayList<IResource>();
        
        for (IResource resource : resourceList) {
            if (resource.isForbidden() != allowed) {
                result.add(resource);
            }
        }
        
        return (IResource[]) result.toArray(IResource.EMPTY_RESOURCES);
    }
    
    public IResource[] getResources(String type) {
        if (StringUtils.isEmpty(type)) {
            return IResource.EMPTY_RESOURCES;
        }
        
        List<IResource> result = new ArrayList<IResource>();
        
        for (IResource resource : resourceList) {
            if (type.equals(resource.getType())) {
                result.add(resource);
            }
        }
        
        return result.toArray(IResource.EMPTY_RESOURCES);
    }
    
    public IResource[] getResources(String type, boolean allowed) {
        if (StringUtils.isEmpty(type)) {
            return IResource.EMPTY_RESOURCES;
        }
        
        List<IResource> result = new ArrayList<IResource>();
        
        for (IResource resource : resourceList) {
            if (type.equals(resource.getType()) && (resource.isForbidden() != allowed)) {
                result.add(resource);
            }
        }
        
        return result.toArray(IResource.EMPTY_RESOURCES);
    }
    
}
